package com.wlps.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wlps.contant.Contant;
import com.wlps.entity.*;
import com.wlps.mapper.CommodityMapper;
import com.wlps.mapper.ReturnOutOfStockMapper;
import com.wlps.mapper.SupplierMapper;
import com.wlps.result.ResultPageVo;
import com.wlps.result.ResultUtils;
import com.wlps.result.ResultVo;
import com.wlps.service.IReturnOutOfStockService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wlps.vo.sendcenter.inoutform.ReturnOutOfStockAddVo;
import com.wlps.vo.warehousecenter.warehoused.ReturnOutOfStockMapping;
import com.wlps.vo.warehousecenter.warehoused.ReturnOutOfStockUpdateVo;
import com.wlps.vo.warehousecenter.warehoused.ReturnOutOfStockVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 退货出库单表(return_out_of_stock) 服务实现类
 * </p>
 *
 * @author ZWYZY
 * @since 2020-07-31
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class ReturnOutOfStockServiceImpl extends ServiceImpl<ReturnOutOfStockMapper, ReturnOutOfStock> implements IReturnOutOfStockService, InitializingBean {
    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    public ReturnOutOfStockMapping returnOutOfStockMapping;

    @Autowired
    CommodityMapper commodityMapper;

    @Autowired
    SupplierMapper supplierMapper;

    @Override
    public void afterPropertiesSet() throws Exception {
        initReturnOutOfStock();
    }

    void initReturnOutOfStock() {
        List<ReturnOutOfStock> returnOutOfStockList;
        if (redisTemplate.hasKey(Contant.RETURNOUTOFSTOCKS_KEY)) {
            returnOutOfStockList = (List<ReturnOutOfStock>) redisTemplate.opsForValue().get(Contant.RETURNOUTOFSTOCKS_KEY);
        } else {
            returnOutOfStockList = baseMapper.selectList(null);
            redisTemplate.opsForValue().set(Contant.RETURNOUTOFSTOCKS_KEY, returnOutOfStockList,5, TimeUnit.MINUTES);
            log.info("初始化所有出库单-------存入缓存数据");
        }
        if (!redisTemplate.hasKey(Contant.RETURNOUTOFSTOCKLIST_KEY)) {
            redisTemplate.opsForList().rightPushAll(Contant.RETURNOUTOFSTOCKLIST_KEY, returnOutOfStockList);
            redisTemplate.expire(Contant.RETURNOUTOFSTOCKLIST_KEY,5,TimeUnit.MINUTES);
            log.info("初始化出库单列表--------存入缓存数据");
        }
    }

    @Override
    public ResultPageVo<List<ReturnOutOfStockVo>> getReturnOutOfStockVo(int pageNum, int pageSize, Long id) {
        initReturnOutOfStock();
        //总条数
        long count;
        List<ReturnOutOfStock> returnOutOfStockList;

        if (id == null) {
            //不是条件查询，redis
            count = (Long) redisTemplate.opsForList().size(Contant.RETURNOUTOFSTOCKLIST_KEY);
            //当前页从第几条开始查
            long fromNum = pageSize * (pageNum - 1);
            if (fromNum >= count) {
                returnOutOfStockList = (List<ReturnOutOfStock>) redisTemplate.opsForList().range(Contant.RETURNOUTOFSTOCKLIST_KEY, 0, count);
            } else {
                //当前页最后第几条
                long toNum = fromNum + pageSize >= count ? count : fromNum + pageSize;
                returnOutOfStockList = (List<ReturnOutOfStock>) redisTemplate.opsForList().range(Contant.RETURNOUTOFSTOCKLIST_KEY, fromNum, toNum-1);
            }

//            RedisConfig.returnJedis(jedis);

        } else {//条件查询，mysql
            Page<ReturnOutOfStock> returnOutOfStockPage = new Page<>(pageNum, pageSize);
            LambdaQueryWrapper<ReturnOutOfStock> queryWrapper = new QueryWrapper<ReturnOutOfStock>().lambda().eq(ReturnOutOfStock::getId, id);
            IPage<ReturnOutOfStock> page = this.baseMapper.selectPage(returnOutOfStockPage, queryWrapper);
            returnOutOfStockList = page.getRecords();
            count = page.getSize();
        }
        //entity  to vo  映射
        List<ReturnOutOfStockVo> returnOutOfStockVoList = returnOutOfStockMapping.entitysToVos(returnOutOfStockList);
        //分页返回值封装
        ResultPageVo resultPageVo = new ResultPageVo("响应成功", 200, (long) pageSize, (long) pageNum, count, returnOutOfStockVoList);

        return resultPageVo;
    }

    @Override
    public ResultVo editReturnOutOfStockVo(Long id, ReturnOutOfStockUpdateVo returnOutOfStockUpdateVo) {
        ReturnOutOfStock searchReturnOutOfStock = baseMapper.selectById(id);
        if (searchReturnOutOfStock == null) {
            return ResultUtils.error("出库单号查询不到，请输入正确的出库单号，亲", 20000);
        }
        if (searchReturnOutOfStock.getTaskStatus() == 1) {
            return ResultUtils.error("已经确认出库,无需重复出库，亲", 20001);
        }
        //1默认为中心库房
        CommodityWarehouse commodityWarehouse = baseMapper.selectCommodityWareHouseByCommodityName(searchReturnOutOfStock.getProductName(), 1);
        if (commodityWarehouse == null) {
            return ResultUtils.error("sorry,库房查询不到商品(" + searchReturnOutOfStock.getProductName() + "),亲", 20002);
        }
        if (returnOutOfStockUpdateVo.getActualVolume() > searchReturnOutOfStock.getQuantityReturned()) {
            return ResultUtils.error("sorry,实际出库数量不能超过商品应出库数量,亲", 20003);
        }
        //计算库存量
        long number = commodityWarehouse.getCurrentNumber() - returnOutOfStockUpdateVo.getActualVolume();
        if (number < 0) {
            return ResultUtils.error("当前商品库存量低于商品实际入库数量，亲，请重新输入实际入库数量", 20004);
        }


        baseMapper.updateCommodityWarehouseCurrentNumber(searchReturnOutOfStock.getProductName(), 1, number);
        ReturnOutOfStock returnOutOfStock = new ReturnOutOfStock();
        returnOutOfStock.setId(id);
        returnOutOfStock.setTaskStatus(1);
        BeanUtils.copyProperties(returnOutOfStockUpdateVo, returnOutOfStock);
        baseMapper.updateById(returnOutOfStock);
        returnOutOfStockUpdateCache();
        return ResultUtils.success("确认出库成功，亲");
    }

    @Override
    public ResultVo<ReturnOutOfStock> addReturnOutOfStockAddVo(ReturnOutOfStockAddVo returnOutOfStockAddVo) {
        Supplier supplier = supplierMapper.selectSupplierByName(returnOutOfStockAddVo.getSupplierName());
        if (supplier == null) {
            return ResultUtils.error("系统未录入该供应商，请先录入供应商信息，亲", 20005);
        }
        Commodity commodity = commodityMapper.selectCommodityByName(returnOutOfStockAddVo.getProductName());
        if (commodity == null) {
            return ResultUtils.error("系统未录入该商品，请先录入商品信息，亲", 20006);
        }
        //1默认为中心库房
        CommodityWarehouse commodityWarehouse = baseMapper.selectCommodityWareHouseByCommodityName(returnOutOfStockAddVo.getProductName(), 1);
        if (commodityWarehouse == null) {
            return ResultUtils.error("中心库房未录入该商品，请先录入商品，亲", 20007);

        }
        if (commodityWarehouse.getOutOfStockNumber() > 0) {
            return ResultUtils.error("当前商品缺货中，不允许出库，亲", 20009);
        }
        long number = commodityWarehouse.getCurrentNumber() - returnOutOfStockAddVo.getQuantityReturned();
        if (number < 0) {
            return ResultUtils.error("当前应出库数量:" + returnOutOfStockAddVo.getQuantityReturned() + "\n大于\n当前商品库存量:" + commodityWarehouse.getCurrentNumber() + " ,\n请重新输入应出库数量，亲", 20008);
        }
        ReturnOutOfStock returnOutOfStock = new ReturnOutOfStock();
        BeanUtils.copyProperties(returnOutOfStockAddVo, returnOutOfStock);
        baseMapper.insert(returnOutOfStock);
        returnOutOfStockUpdateCache();
        return ResultUtils.success("生成出库单成功，亲", returnOutOfStock);
    }


    /**
     * 更新缓存
     */
    @Async
    public void returnOutOfStockUpdateCache() {
        List<ReturnOutOfStock> returnOutOfStockList = baseMapper.selectList(null);
        redisTemplate.opsForValue().set(Contant.RETURNOUTOFSTOCKS_KEY, returnOutOfStockList,5,TimeUnit.MINUTES);
        redisTemplate.delete(Contant.RETURNOUTOFSTOCKLIST_KEY);
        redisTemplate.opsForList().rightPushAll(Contant.RETURNOUTOFSTOCKLIST_KEY, returnOutOfStockList);
        redisTemplate.expire(Contant.RETURNOUTOFSTOCKLIST_KEY,5,TimeUnit.MINUTES);
        redisTemplate.delete(Contant.INOUTVOS_KEY);
        log.info("所有出库单-------更新缓存数据");
    }

}
